package usersManagement.service;

import org.slf4j.Logger;
import usersManagement.model.User;
import usersManagement.repository.UserRepository;
import usersManagement.util.AppLog;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.io.Serializable;
import java.net.URI;
import java.util.List;

/**
 * User: eluibon
 * Date: 11/12/12
 * Time: 14.06
 */
@Path("/admin")
@Stateless
public class UserService implements Serializable {
// ------------------------------ FIELDS ------------------------------

    private static final long serialVersionUID = 2332677310929733841L;

    @Inject @AppLog
    Logger log;

    @Inject
    UserRepository userRepository ;

// -------------------------- OTHER METHODS --------------------------

    @POST
    @Path("/user")
    @Consumes("application/json")
    public Response create(User user, @Context UriInfo uriInfo) {
        // TODO
        // what if the client pass the ID of the user instead of allowing JPA/Hib to generate it ?
        // should we avoid mapping the id to json ?


        try {
            save(user);
            final URI uri = uriInfo.getAbsolutePathBuilder().path(user.getId().toString()).build();
            return Response.created(uri).status(201).entity("ok").build();
        }
        catch (DuplicateUsernameException e) {
            return Response.status(403).entity(e.getMessage()).build();
        }
        catch (ConstraintViolationException cve) {
            return Response.status(403).entity(cve.getMessage()).build(); // message needs to be better constructed but to be parsable client side
        }
    }

    public void save(User user) throws DuplicateUsernameException {
        log.info("Saving user : {}", user);
        User userCheck = findByUsername(user.getUsername());
        if ((userCheck != null) && (!userCheck.getId().equals(user.getId()))) {
            // trying to save a user with an already existing username
            throw new DuplicateUsernameException("Username already exists !");
        }
        else
            userRepository.saveAndFlush(user) ;
    }

    public User findByUsername(String username) {
        return userRepository.findByUsername(username) ;
    }

    @GET
    @Path("/users")
    @Produces("application/json")
    public List<User> findAll() {
        return userRepository.findAll();
    }

    @GET
    @Path("/user/{id}")
    @Produces("application/json")
    public User findById(@PathParam("id") Long id) {
        return userRepository.findOne(id);
    }

    @PUT
    @Path("/user")
    @Consumes("application/json")
    public Response update(User user) {
        // TODO : what about user identity on update ? should we update to /user/{id}, load it (if exists?) and merge ?
        try {
            save(user);
            return Response.status(201).entity("ok").build();
        }
        catch (DuplicateUsernameException e) {
            return Response.status(403).entity(e.getMessage()).build();
        }
        catch (ConstraintViolationException cve) {
            return Response.status(403).entity(cve.getMessage()).build(); // message needs to be better constructed but to be parsable client side
        }
    }
}
